/*
 *   Copyright 2021 zzh
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */

package com.aduib.boot.common.serialization.protobuf;

import com.aduib.boot.common.serialization.api.ObjectReader;
import com.google.protobuf.BoolValue;
import com.google.protobuf.BytesValue;
import com.google.protobuf.DoubleValue;
import com.google.protobuf.FloatValue;
import com.google.protobuf.Int32Value;
import com.google.protobuf.Int64Value;
import com.google.protobuf.StringValue;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;

public class GenericProtobufObjectReader implements ObjectReader {
  private final InputStream is;

  public GenericProtobufObjectReader(InputStream is) {
    this.is = is;
  }

  @Override
  public boolean readBoolean() throws IOException {
    return read(BoolValue.class).getValue();
  }

  @Override
  public byte readByte() throws IOException {
    return (byte) read(Int32Value.class).getValue();
  }

  @Override
  public short readShort() throws IOException {
    return (short) read(Int32Value.class).getValue();
  }

  @Override
  public int readInt() throws IOException {
    return read(Int32Value.class).getValue();
  }

  @Override
  public long readLong() throws IOException {
    return read(Int64Value.class).getValue();
  }

  @Override
  public float readFloat() throws IOException {
    return read(FloatValue.class).getValue();
  }

  @Override
  public double readDouble() throws IOException {
    return read(DoubleValue.class).getValue();
  }

  @Override
  public String readUtfString() throws IOException {
    return read(StringValue.class).getValue();
  }

  @Override
  public byte[] readBytes() throws IOException {
    return read(BytesValue.class).getValue().toByteArray();
  }

  @Override
  public <T> T readObject(Class<T> cls) throws IOException {
    return read(cls);
  }

  @Override
  public <T> T readObject(Class<T> cls, Type type) throws IOException {
    return readObject(cls);
  }

  @SuppressWarnings("unchecked")
  private <T> T read(Class<T> cls) throws IOException {
    if (!ProtobufUtils.isSupported(cls)) {
      throw new IllegalArgumentException(
          "This serialization only support google protobuf messages, but the actual input type is :"
              + cls.getName());
    }

    return ProtobufUtils.deserialize(is, cls);
  }
}
